package web.exception;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DefaultExceptionHandler extends ExceptionHandlerWrapper {
	private static final Log LOG = LogFactory
			.getLog(DefaultExceptionHandler.class);

	/** key for session scoped message detail */
	public static final String MESSAGE_DETAIL_KEY = "ip.client.jsftoolkit.messageDetail";

	private ExceptionHandler wrapped;

	public DefaultExceptionHandler(ExceptionHandler wrapped) {
		this.wrapped = wrapped;
	}

	@Override
	public ExceptionHandler getWrapped() {
		return this.wrapped;
	}

	@Override
	public void handle() throws FacesException {
		// Iterate over all unhandeled exceptions
		Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents()
				.iterator();
		while (i.hasNext()) {
			ExceptionQueuedEvent event = i.next();
			ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event
					.getSource();

			// obtain throwable object
			Throwable t = context.getException();

			// here you do what ever you want with exception
			try {
				// log error
				LOG.error("Serious error happened!", t);
				// redirect to error view etc....
			} finally {
				// after exception is handeled, remove it from queue
				i.remove();
			}
		}
		// let the parent handle the rest
		getWrapped().handle();
	}

	protected String handleUnexpected(FacesContext facesContext,
			final Throwable t) {
		LOG.error("An unexpected internal error has occurred", t);

		return "jsftoolkit.exception.UncheckedException";
	}
}
